#!/bin/sh

set -x

panic()
{
	echo "$@"
	exit
}

# Default PATH differs between shells, and is not automatically exported
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

[ -d /dev ] || mkdir -m 0755 /dev
[ -d /root ] || mkdir -m 0700 /root
[ -d /sys ] || mkdir /sys
[ -d /proc ] || mkdir /proc
[ -d /run ] || mkdir /run
[ -d /tmp ] || mkdir /tmp
mkdir -p /var/lock
mount -t sysfs -o nodev,noexec,nosuid sysfs /sys
mount -t proc -o nodev,noexec,nosuid proc /proc

# Note that this only becomes /dev on the real filesystem if udev's scripts
# are used; which they will be, but it's worth pointing out
mount -t devtmpfs -o nosuid,mode=0755 udev /dev

mkdir /dev/pts
mount -t devpts -o noexec,nosuid,gid=5,mode=0620 devpts /dev/pts || true

export init=/init
export readonly=y
export rootmnt=/roottmp
export ROOT=
export DATA=

# Parse command line options
for x in $(cat /proc/cmdline); do
	case $x in
	# The following lines blocked for security reason
	init=*)
		init=${x#init=}
		;;
	root=*)
		ROOT=${x#root=}
		;;
	data=*)
		DATA=${x#data=}
		;;
	ro)
		readonly=y
		;;
	rw)
		readonly=n
		;;
	esac
done

mount -t tmpfs -o "nodev,noexec,nosuid,size=${RUNSIZE:-10%},mode=0755" tmpfs /run
mkdir -m 0700 /run/initramfs

# rootmnt mount from rootfs
if [ -z "${ROOT}" ]; then
	panic "No root device specified. Boot arguments must include a root= parameter."
fi

##虚拟机测试需要单独加个驱动
#ls /
#insmod /lib/modules/4.19.0-arm64-desktop/kernel/drivers/scsi/virtio_scsi.ko

dev_uuid=${ROOT#UUID=}
ROOTDEV=
case ${ROOT} in
	UUID=*)
		ROOTDEV=/dev/disk/by-uuid/${dev_uuid}
		;;
	LABEL=*)
		ROOTDEV=/dev/disk/by-label/${ROOT#LABEL=}
		;;
	*)
		ROOTDEV=${ROOT}
		;;
esac

ROOTDISK=
if [ -L "$ROOTDEV" ]; then 
	ROOTDISK=$(readlink -f "$ROOTDEV")
else
	ROOTDISK=$(blkid | grep ${dev_uuid} | awk -F: '{print $1}')
fi

if [ -z "${ROOTDISK}" ]; then
	panic "No root device specified. Boot arguments must include a root= parameter.."
fi

dat_uuid=${DATA#UUID=}
DATADEV=
case ${DATA} in
	UUID=*)
		DATADEV=/dev/disk/by-uuid/${dat_uuid}
		;;
	LABEL=*)
		DATADEV=/dev/disk/by-label/${DATA#LABEL=}
		;;
	*)
		DATADEV=${ROOT}
		;;
esac

DATADISK=
if [ -L "$DATADEV" ]; then 
	DATADISK=$(readlink -f "$DATADEV")
else
	DATADISK=$(blkid | grep ${dat_uuid} | awk -F: '{print $1}')
fi


rootdev=/media/rootdev
mkdir -p ${rootdev}
if mount ${ROOTDISK} ${rootdev}; then
	echo "mount ${ROOT} success."
	ls ${rootdev}
else
	panic "No root device specified. Boot arguments must include a root= parameter."
fi
fs=${rootdev}/ramfs.squashfs
if [ -f ${fs} ]; then
	echo "mount file system..."
else
	panic "File system no found. Check whether the system partition is successfully written" 
fi

# 这里应该叠加overlay的挂载; 如果未指定data分区则只读启动系统
mkdir -p ${rootmnt}
real_path=/media/realfs
mkdir -p ${real_path}
mount -o ro,nosuid,nodev,relatime ${fs} ${real_path}
data_path=
use_overlay=1
if [ -z "${DATADISK}" ]; then
	echo "No data device specified. Boot arguments must include a data= parameter.."
	if mount -t tmpfs -o "nodev,noexec,nosuid,size=256M,mode=0755" tmpfs ${rootmnt}; then
		echo "Boot system on tmpfs" 
		data_path=${rootmnt}
	else
		echo "Read-only boot system" 
		if mount -r ${fs} ${rootmnt}; then
			user_overlay=0
			echo "mount file system success."
		else
			panic "File system mount failed. Check whether the system partition is successfully written" 
		fi
	fi
else
	data_path=/media/data
	mkdir -p ${data_path}
	if mount -o rw,nosuid,nodev,relatime ${DATADISK} ${data_path}; then
		ls ${data_path}
	else
		panic "File system mount failed. Check whether the data partition is available" 
	fi
	
fi
if [ $use_overlay -eq 1 ]; then 
	overlay_root=${data_path}/rootfs
	mkdir -p ${overlay_root}
	mkdir -p ${overlay_root}/lowerdir
	mkdir -p ${overlay_root}/upperdir
	mkdir -p ${overlay_root}/workdir
	mount -o bind ${real_path} ${overlay_root}/lowerdir 
	if mount -t overlay -o lowerdir=${overlay_root}/lowerdir,upperdir=${overlay_root}/upperdir,workdir=${overlay_root}/workdir overlay ${rootmnt}; then
		echo "mount file system success."
	else
		panic "File system mount failed. Check whether the system partition is successfully written" 
	fi
fi

# Move /run to the root
mount -n -o move /run ${rootmnt}/run

validate_init() {
	run-init -n "${rootmnt}" "${1}"
}

# Check init is really there
if ! validate_init "$init"; then
	echo "Target filesystem doesn't have requested ${init}."
	init=
	for inittest in /init /sbin/init /etc/init /bin/init /bin/sh; do
		if validate_init "${inittest}"; then
			init="$inittest"
			break
		fi
	done
fi

# No init on rootmount
if ! validate_init "${init}" ; then
	panic "No init found. Try passing init= bootarg."
fi

# Move virtual filesystems over to the real filesystem
mkdir -p ${rootmnt}/dev/pts
mount -n -o move /sys ${rootmnt}/sys
mount -n -o move /proc ${rootmnt}/proc
mount -n -o move /dev ${rootmnt}/dev
mount -n -o move /dev/pts ${rootmnt}/dev/pts

mkdir ${rootmnt}/data
mount -n -o move  ${data_path} ${rootmnt}/data

# Chain to real filesystem
exec run-init "${rootmnt}" "${init}" /data "$@" <"${rootmnt}/dev/console" >"${rootmnt}/dev/console" 2>&1
echo "Something went badly wrong in the initramfs."
panic "Please file a bug on initramfs-tools."
